#include "device.h"

cv::VideoCapture cap;
uint sleepTimeMS = 1;

bool readFrame(cv::Mat& frame) {
    cv::waitKey(sleepTimeMS);
    return cap.read(frame);
}

bool Camera::open(uint index, uint width, uint height, float fps, bool flag) {
    cap.open(index, cv::CAP_DSHOW);
    if (!cap.isOpened()) return false;
    cap.set(cv::CAP_PROP_FRAME_WIDTH, (double)width);
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, (double)height);
    cap.set(cv::CAP_PROP_FPS, (double)fps);
    this->width = (uint)cap.get(cv::CAP_PROP_FRAME_WIDTH);
    this->height = (uint)cap.get(cv::CAP_PROP_FRAME_HEIGHT);
    this->fps = (float)cap.get(cv::CAP_PROP_FPS);
    if (flag) measureFPS();
    printf("Camera ON: %dx%d, %.2f FPS. \n", this->width, this->height, this->fps);
    return true;
}

void Camera::config(double brightness, double contrast, double saturation, double hue, double gain, double exposure) {
    cap.set(cv::CAP_PROP_BRIGHTNESS, brightness);
    cap.set(cv::CAP_PROP_CONTRAST, contrast);
    cap.set(cv::CAP_PROP_SATURATION, saturation);
    cap.set(cv::CAP_PROP_HUE, hue);
    cap.set(cv::CAP_PROP_GAIN, gain);
    cap.set(cv::CAP_PROP_EXPOSURE, exposure);
    printf("Camera Params: \n");
    printf("  brightness = %.2f\n", cap.get(cv::CAP_PROP_BRIGHTNESS));
    printf("  contrast = %.2f\n", cap.get(cv::CAP_PROP_CONTRAST));
    printf("  saturation = %.2f\n", cap.get(cv::CAP_PROP_SATURATION));
    printf("  hue = %.2f\n", cap.get(cv::CAP_PROP_HUE));
    printf("  gain = %.2f\n", cap.get(cv::CAP_PROP_GAIN));
    printf("  exposure = %.2f\n", cap.get(cv::CAP_PROP_EXPOSURE));
}

void Camera::measureFPS() {
    printf("Measure FPS ...");
    cv::Mat frame;
    uint num = 300;
    uint64 t1 = cv::getTickCount();
    for (uint i = 0; i < num; i++) {
        cap >> frame;
    }
    float sec = (float)(cv::getTickCount() - t1) / (float)cv::getTickFrequency();
    this->fps = num / sec;
    printf("Done.\n");
}

// ********************************************

bool Video::open(const char* path) {
    cap.open(path);
    if (!cap.isOpened()) return false;
    this->width = (uint)cap.get(cv::CAP_PROP_FRAME_WIDTH);
    this->height = (uint)cap.get(cv::CAP_PROP_FRAME_HEIGHT);
    this->count = (uint)cap.get(cv::CAP_PROP_FRAME_COUNT);
    this->fps = (float)cap.get(cv::CAP_PROP_FPS);
    printf("Open video: %s\n", path);
    printf("Video INFO: about %d frames, %dx%d, %.2f FPS\n", count, width, height, fps);
    sleepTimeMS = 1000 / (uint)fps;
    return true;
}

// ********************************************

Recorder::~Recorder() {
    recorder.release();
}

bool Recorder::open() {
    getSavePath();
    int fourcc = recorder.fourcc('m', 'p', '4', 'v');   // mp4
    auto size = cv::Size(width, height);
    recorder.open(this->path, fourcc, fps, size);
    if (!recorder.isOpened()) return false;
    printf("Start recording ... %s: %dx%d, %.2f FPS\n", this->path, width, height, fps);
    return true;
}

void Recorder::write(cv::Mat& frame) {
    recorder.write(frame);
}


#include <direct.h>     // _mkdir
#include <io.h>         // _access
#include <ctime>        // time
void Recorder::getSavePath() {
    const char* folder = "./videos";
    if (0 != _access(folder, 0)) {
        auto _ = _mkdir(folder);
    }
    time_t unixtime = time(nullptr);
    tm now;
    localtime_s(&now, &unixtime);
    sprintf_s(this->path, 100, "%s/record_%4d%02d%02d_%02d%02d.mp4", folder,
        1900 + now.tm_year, 1 + now.tm_mon, now.tm_mday,
        now.tm_hour, now.tm_min);
}

